﻿using System;
using System.ComponentModel;
using System.Text;
using System.Web.Mvc;
using ContactMvc4TB.Helpers.MvcBasics;
using ContactMvc4TB.Helpers.RightsManagement;
using ContactMvc4TB.Models.Worktime;
using ContactMvc4TB.Models.Worktime.Helpers;
using EFDataModel;

namespace ContactMvc4TB.Controllers
{
    /// <summary>
    /// CurrentController für die Arbeitszeiterfassung
    /// </summary>
    [CustomAuthorize]
    public class WorktimeController : Controller
    {
        /// <summary>
        /// Laden des passenden Worktimeeintrags
        /// </summary>
        /// <param name="id">WorktimeId die angezeigt werden soll bei "0" wird ein Neuer Eintrag angelegt</param>
        /// <param name="userId">die Userid für die der Eintrag angelegt/angezeigt werden soll</param>
        public ActionResult Worktime(long id, long userId)
        {
            CreateWorktimeEntryModel model = new CreateWorktimeEntryModel(this, userId);
            model.LoadModelData(id);
            return View(model);
        }

        /// <summary>
        /// Laden des passenden Datums um dafür einen Worktimeeintrag anlegen zu können
        /// </summary>
        /// <param name="datum">Der Tag für den die Modeldaten geladen werden sollen.</param>
        /// <param name="id">die worktimeId </param>
        /// <param name="userId">die Userid für die der Eintrag angelegt/angezeigt werden soll</param>
        public ActionResult WorktimeByDate(long id, long userId, DateTime? datum)
        {
            CreateWorktimeEntryModel model = new CreateWorktimeEntryModel(this, userId);
            model.LoadModelData(datum);
            return View(EActionWorktime.Worktime.ToString(), model);
        }

        /// <summary>
        /// Löschen des passenden Worktimeeintrags
        /// </summary>
        /// <param name="id">WorktimeId die gelöscht werden soll</param>
        /// <param name="userId">die Userid für die der Eintrag gelöscht werden soll</param>
        public ActionResult DeleteWorktime(long id, long userId)
        {
            DeleteWorktimeEntryModel model = new DeleteWorktimeEntryModel(this);
            long user = userId;
            DateTime date = model.DeleteWorktimeEntry(id, userId);
            //Den Nächsten Standardeintrag für den aktuellen Tag anzeigen, und dabei die passende Action ByDate aufrufen.
            return RedirectToAction(EActionWorktime.WorktimeByDate.ToString(), EControllers.Worktime.ToString(), new { id = 0, userId = user, datum = date.ToString(WebConstants.InputDateTimeFormat) });
        }

        /// <summary>
        /// Laden des passenden Worktimeeintrags
        /// </summary>
        /// <param name="model">Die Modeleinträge für den Worktime Eintrag der angelegt werden soll.</param>
        /// <param name="id">WorktimeId die angezeigt werden soll bei "0" wird ein Neuer Eintrag angelegt</param>
        /// <param name="userId">die Userid für die der Eintrag angelegt/angezeigt werden soll</param>
        [HttpPost]
        public ActionResult Worktime(CreateWorktimeEntryModel model, long id, long userId)
        {
            if (ModelState.IsValid)
            {
                //Achtung initialize Model muss immer als erstes aufgerufen werden.
                model.InitializeModel(this, userId);
                model.ExcecuteBySubmitType(id);
                ModelState.Clear();
            }
            else
            {
                model.InitializeModel(this, userId);
                model.LoadDefaultData();
            }

            //Beim Anlegen eines Eintrags bzw. nach dem Bearbeiten eines Eintrags, muss in der URL wieder eine 0 für WorktimeId stehen
            //sonst wird der aktuelle eintrag bearbeitet, daher muss hier immer ein Redirect durchgeführt werden.

            return View(model);
        }

        public ActionResult WorktimeIndex()
        {
            return RedirectToAction(EActionWorktime.Worktime.ToString(), EControllers.Worktime.ToString(), new { id = 0, userId = CurrentSession.GetCurrentUser().ID });
        }

        /// <summary>
        /// Anzeigen des passenden Datums.
        /// </summary>
        /// <param name="model">Die Modeleinträge für den Worktime Eintrag der angelegt werden soll.</param>
        /// <param name="id">WorktimeId die angezeigt werden soll bei "0" wird ein Neuer Eintrag angelegt</param>
        /// <param name="userId">die UserId für die der Eintrag angelegt werden soll </param>
        /// <param name="datum">Das Datum für das die Liste geladen werden soll.</param>
        [HttpPost]
        public ActionResult WorktimeByDate(CreateWorktimeEntryModel model, long id, long userId, DateTime? datum)
        {
            if (ModelState.IsValid)
            {
                model.InitializeModel(this, userId);
                //Wenn diese Postbackfunktion aufgerufen wurde, dann wurde kein direkter Arbeitszeit eintrag geladen, sondern es wurde
                //das datum ausgewählt um z.b. direkt für das Datum einen Eintrag anzulegen, daher kann hier imm 0 übergeben werden.
                model.ExcecuteBySubmitType(0);
                ModelState.Clear();
            }
            else
            {
                model.InitializeModel(this, id);
            }

            return View(EActionWorktime.Worktime.ToString(), model);
        }

        /// <summary>
        /// Das Heutige Datum laden uns anzeigen
        /// </summary>
        /// <param name="userId">die UserId für die der Eintrag geladen werden soll</param>
        /// <param name="id">Die worktimeId</param>
        public ActionResult LoadToday(long userId, long id)
        {
            long user = userId;
            return RedirectToAction(EActionWorktime.WorktimeByDate.ToString(), EControllers.Worktime.ToString(), new { id = 0, userId = user, datum = DateTime.Now.ToString(WebConstants.InputDateTimeFormat) });
        }

        /// <summary>
        /// Den letzten Arbeitstag ermitteln an dem noch kein Arbeitszeiteintrag hinterlegt wurde.
        /// </summary>
        /// <param name="id">Die WorktimeId</param>
        /// <param name="userId">Die UserId für die das Datum geladen werden soll</param>
        public ActionResult LoadLastFreeDay(long id, long userId)
        {
            //Letzten Freien Tag ermitteln
            CalculateNoWorktimeEntryDays calculate = new CalculateNoWorktimeEntryDays(userId);
            DateTime date = calculate.GetLastNoWorktimeEntryDayCurrentYear();

            long user = userId;
            return RedirectToAction(EActionWorktime.WorktimeByDate.ToString(), EControllers.Worktime.ToString(), new { id = 0, userId = user, datum = date.ToString(WebConstants.InputDateTimeFormat) });
        }

        /// <summary>
        /// Bearbeiten bzw. anlegen der Settings.
        /// </summary>
        /// <param name="id">die UserId für die die Settings angezeigt werden sollen.</param>
        public ActionResult EditWorktimeSettings(long id)
        {
            EditWorktimeSettingsModel model = new EditWorktimeSettingsModel(this);
            model.LoadModelData(id);
            return View(model);
        }

        [HttpPost]
        public ActionResult EditWorktimeSettings(EditWorktimeSettingsModel model, long id)
        {
            if (ModelState.IsValid)
            {
                //Speichern/Anlegen der Modeldaten
                model.SaveModelData(id, this);
            }

            return View(model);
        }

        /// <summary>
        /// Anzeigen der Urlaubsliste
        /// </summary>
        /// <param name="id">die UserId für die die Liste angezeigt werden sollen.</param>
        public ActionResult HolidayList(long id)
        {
            HolidayListModel model = new HolidayListModel();
            if (model.LoadModelData(id))
            {
                return View(model);
            }

            //Wenn keine Daten gefunden wurde, dann direkt versuchen einen Eintrag anzulegen.
            return RedirectToAction(EActionWorktime.HolidayCreate.ToString(), EControllers.Worktime.ToString(), new { id = 0, userId = id });
        }

        /// <summary>
        /// Anzeigen der Urlaubszeitbearbeitung
        /// </summary>
        /// <param name="id">die UserId für die die Liste angezeigt werden sollen.</param>
        public ActionResult HolidayCreate(int id, long userId)
        {
            HolidayCreateModel model = new HolidayCreateModel();
            //Nur wenn das Laden der Daten erfolgreich war auch anzeigen, sonst wird auf den Settings Screen zurück verwiesen.
            if (model.LoadModelData(this, id, userId))
            {
                return View(model);
            }

            return RedirectToAction(EActionWorktime.EditWorktimeSettings.ToString(), EControllers.Worktime.ToString(), new { id = 0 });
        }

        /// <summary>
        /// Urlaubszeitbearbeitung speichern/erstellen
        /// </summary>
        /// <param name="id">die UserId für die die Liste angezeigt werden sollen.</param>
        [HttpPost]
        public ActionResult HolidayCreate(HolidayCreateModel model, int id, long userId)
        {
            if (ModelState.IsValid)
            {
                //Beim erfolgreichen Speichern auf die Liste mit den Einträgen verweisen.
                if (model.SaveModelData(this, id, userId))
                {
                    return RedirectToAction(EActionWorktime.HolidayList.ToString(), EControllers.Worktime.ToString(), new { id = userId });
                }
            }

            return View(model);
        }

        /// <summary>
        /// Anzeigen der eigenen Projektliste.
        /// </summary>
        /// <param name="id">Die UserId für die die Liste angezeigt werden soll</param>
        public ActionResult WorktimeProjectList(int id)
        {
            WorktimeProjectListModel model = new WorktimeProjectListModel();
            if(!model.LoadModelData(id))
            {
                //Wenn noch kein Eintrag existiert, direkt zum Eintrag springen um einen neuen anzulegen.
                return RedirectToAction(EActionWorktime.WorktimeProjectCreate.ToString(), EControllers.Worktime.ToString(), new { id = 0, userId = id });
            }

            return View(model);
        }

        /// <summary>
        /// Anzeigen der eigenen Projektliste.
        /// </summary>
        /// <param name="id">Die UserId für die die Liste angezeigt werden soll</param>
        public ActionResult WorktimeProjectDelete(long id, long userId)
        {
            WorktimeProjectCreateModel model = new WorktimeProjectCreateModel();
            model.InitializeData(this, userId, id);
            model.DeleteProjectEntry();

            return RedirectToAction(EActionWorktime.WorktimeProjectList.ToString(), EControllers.Worktime.ToString(), new { id = userId });
        }

        /// <summary>
        /// Laden der Daten für das Anlegen/Bearbeiten eine Projekteintrags.
        /// </summary>
        /// <param name="id">passende ProjektId</param>
        /// <param name="userId">zugehörige UserId</param>
        public ActionResult WorktimeProjectCreate(long id, long userId)
        {
            WorktimeProjectCreateModel model = new WorktimeProjectCreateModel();
            model.InitializeData(this, userId, id);
            model.LoadModelData();
            return View(model);
        }

        /// <summary>
        /// Laden der Daten für das Anlegen/Bearbeiten eine Projekteintrags.
        /// </summary>
        /// <param name="id">passende ProjektId</param>
        /// <param name="userId">zugehörige UserId</param>
        [HttpPost]
        public ActionResult WorktimeProjectCreate(WorktimeProjectCreateModel model, long id, long userId)
        {
            model.InitializeData(this, userId, id);
            if(model.SaveModelData())
            {
                //Beim Erfolgereichen Speichern, wieder auf die Liste der Projekte verweisen.
                return RedirectToAction(EActionWorktime.WorktimeProjectList.ToString(), EControllers.Worktime.ToString(), new { id = userId });
            }

            return View(model);
        }

        /// <summary>
        /// Download aller eingetragenenen Arbeitszeiteinträge.
        /// </summary>
        /// <param name="id">UserId für die die Einträge heruntergeladen werden sollen.</param>
        public FileResult WorktimeDownloadAllData(long id)
        {
            string content = WorktimeHelper.DownloadAllData(id);
            byte[] array = Encoding.Unicode.GetBytes(content);
            return File(array, "application/CSV");
        }

        /// <summary>
        /// Die Filter für die Listenansicht setzten auf Täglich
        /// </summary>
        public ActionResult WorktimeDailyFilter(long id)
        {
            WorktimeHelper.SetWorktimefilter(EWorktimeListTypes.ByDay);
            return RedirectToAction(EActionWorktime.Worktime.ToString(), EControllers.Worktime.ToString(),new {id = 0, userId = id});
        }

        /// <summary>
        /// Die Filter für die Listenansicht setzten auf bei Eintrag anzeigen
        /// </summary>
        public ActionResult WorktimeLastEntryFilter(long id)
        {
            WorktimeHelper.SetWorktimefilter(EWorktimeListTypes.ByEntries);
            return RedirectToAction(EActionWorktime.Worktime.ToString(), EControllers.Worktime.ToString(), new { id = 0, userId = id });
        }
    }
}
